{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from utils import *\n",
    "\n",
    "PAIR = 0  # physical core ID\n",
    "CORES = scan_ht_cores()[PAIR]\n",
    "platform = get_uarch()\n",
    "BIN = f'{BUILD_DIR}/bino'\n",
    "RES_DIR = Path('results')\n",
    "\n",
    "if not RES_DIR.exists():\n",
    "    RES_DIR.mkdir()\n",
    "assert(RES_DIR.is_dir())\n",
    "\n",
    "\n",
    "def run_bino(cores, name, iters=5):\n",
    "    cmd = [BIN, name, ] + cores\n",
    "    lats = np.zeros(0x200)\n",
    "    for _ in range(iters):\n",
    "        lats += run_once(cmd, '-', None)[0][:, 1].astype('float64')\n",
    "    return lats / iters\n",
    "\n",
    "\n",
    "def run_contention_effect(cores, alias=True):\n",
    "    cmd = [BIN, 'contention_effect', ] + cores + [str(int(alias))]\n",
    "    lats = run_once(cmd, '-', None)[0].astype('float64')\n",
    "    return lats\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ninja: no work to do.\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Demonstrate the contention effect that is exploited by Binoculars\n",
    "# Correspond to\n",
    "# Figure 2: Distribution of the latency of a TLB-missing access\n",
    "# while the sibling hyperthread keeps issuing writes whose\n",
    "# address may or may not alias with the page walker loads\n",
    "\n",
    "def plot_contention_effect(xlim=(1.5, 4.5), step=.05, nsamples=100, **kwargs):\n",
    "    no_alias = run_contention_effect(CORES, alias=False)\n",
    "    fk_alias = run_contention_effect(CORES, alias=True)\n",
    "    fig, ax = plt.subplots(figsize=(6, 3))\n",
    "    ax.set_xlim(*xlim)\n",
    "    ax.set_ylim(0, nsamples)\n",
    "    ax.hist(np.log10(no_alias), bins=np.arange(*xlim, step), density=False, label='No aliasing')\n",
    "    ax.hist(np.log10(fk_alias), bins=np.arange(*xlim, step), density=False, label='4K-aliasing')\n",
    "\n",
    "    ax.set_ylabel('Sample Count', fontsize=10)\n",
    "    ax.set_xlabel('$\\\\log_{10}$ Latency', fontsize=10)\n",
    "    ax.legend(loc='upper left', ncol=2, fontsize=10)\n",
    "    fig.tight_layout()\n",
    "    fig.savefig(RES_DIR / f'contention_effect_{platform}.pdf', bbox_inches='tight')\n",
    "\n",
    "plt.close('all')\n",
    "rebuild()\n",
    "fig = plot_contention_effect()\n",
    "plt.show(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ninja: no work to do.\n"
     ]
    },
    {
     "data": {
      "image/png": "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unWZN28ev/nNb+jatSuZmZksXboUgDlz5jBt2jQyMjI4+eST+eabb4qcd/To0XTq1Inu3bvTpUsXfvnLX7J//34yMjKoXbs2Xbt2LdJJokGDBrzwwgtMmTKFjh07csIJJ9CrVy+uvfbaEt/HokWL6Nq1K926dWPu3Llcf/31tG7dmkceeYSLL76YjIwMevfuzccffwzAVVddxZlnnpnSThJxp9sws4HAzQSTCr4HfAfUB44FjiYYCPYv7r49NaEeoOk20tsjjzzC7NmzMTOmT59O9+7dY+7XoUMHjjzySADOOOMMbr31Vl577TUmTZpEvXr1aNSoEXPmzKFly5YsX76ca6+9tqB87ty5NGnSJJVvS9KEpttIP8mabiNu7wmCGXDbxdl2CHAeMKy8vTTK8lIvvvS1efNm79atm+/du9fXrVvnffr0ibvv0UcfXaTsyy+/9D179ri7+3333ecTJkxwd/dhw4YV9JaaNGmSz5gxIwnRS1VQ6l58knTJ6sUX91adu9/o7v+Ns22/uz/v7v8oV3aUauedd96hX79+1K1blw4dOpCTk8Mdd9zB73//ewAuu+wynn32WSD442jgwIGceeaZBdNet2vXruD5knr16nHIIUE/ns6dO7N161YAtmzZQps2bVL7xkQk5RJpg7rezJpa4CEze9fMBqUiOKl6Nm3aRPPmzQvWmzVrxqWXXspbb73FDTfcQKNGjRg6dCgAb7/9NllZWdxxxx2MHDnyoPN8++233HvvvYwZMwaAYcOGMXbsWLp06cKyZcs499xzU/emJO14kmYCl9JL5v9FIp0dRnnQzjQIaA78HJiatIikSmvRokVBTQeCZzlatGjBuHHjuPfee5kwYULBtlatWgHQtWtXGjZsyJYtWwDYvn07F1xwATNnziyoKV199dU899xzfPjhhwwZMqRIY7HUHPXr12fTpk1KUmnA3dm0adNBz3ZVpESeg7Lw37OAOe7+kZlZcQdIzXXSSScxYcIEcnNz2bBhA40bN2b//v1MmjSJmTNnMnbsWObNm8fevXtxd+rXr89XX33F1q1badasGbt37+b888/n1ltv5aSTTio4r7sXJLQ2bdoUdIOVmqdt27asX7+ejRs3VnYoQvAHQ9u2bZNy7kQS1Aozmw90AG4xsyZAflKikSqvefPmXHPNNfTv3x8z469//SvXXXcd48eP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",
      "text/plain": [
       "<Figure size 432x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Demonstrate the store->load channel (i.e., store offset extraction)\n",
    "# Correspond to Figure 4\n",
    "\n",
    "def plot_store_offset(step=5000, **kwargs):\n",
    "    name = 'store_offset'\n",
    "    lats = run_bino(CORES, name, **kwargs)\n",
    "\n",
    "    offsets = np.arange(0, 0x1000, 8)\n",
    "    peak = max(range(len(lats)), key=lats.__getitem__)\n",
    "    fig, ax = plt.subplots(figsize=(6, 3))\n",
    "\n",
    "    ax.plot(offsets, lats, label='Latency')\n",
    "    ax.plot(offsets[peak], lats[peak], 'rx', label='Secret Offset')\n",
    "    ax.text(offsets[peak], lats[peak] + 1000, f'{offsets[peak]:#x}', ha='center', fontsize=9)\n",
    "\n",
    "    ax.set_xlim(offsets[0], offsets[-1])\n",
    "\n",
    "    max_y = 22000\n",
    "    ax.set_ylim(0, max_y)\n",
    "\n",
    "    ax.set_xticks(list(np.arange(0, 0x1000, 0x200)) + [0xfff])\n",
    "    ax.set_xticklabels([f'{t:#x}' for t in ax.get_xticks()], fontsize=9)\n",
    "\n",
    "    ax.set_yticks(np.arange(0, max_y + .1, step))\n",
    "    ax.set_yticklabels([f'{t / 1000:.0f}k' for t in ax.get_yticks()], fontsize=9)\n",
    "\n",
    "    ax.set_xlabel('Page Offset', fontsize=10)\n",
    "    ax.set_ylabel('Avg. Latency (cycles)', fontsize=10)\n",
    "    ax.legend(loc='upper right', fontsize=10)\n",
    "\n",
    "    fig.tight_layout()\n",
    "    fig.savefig(RES_DIR / f'prim_{name}_{platform}.pdf', bbox_inches='tight')\n",
    "\n",
    "plt.close('all')\n",
    "rebuild()\n",
    "fig = plot_store_offset(step=5000, iters=1)\n",
    "plt.show(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ninja: no work to do.\n"
     ]
    },
    {
     "data": {
      "image/png": "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227SpAlXXHEFH3zwATfeeCMNGjRg6NChnsdt27aN1q1bs3r1ahYtWkTv3r251Y29f/XVV+zevZv8/Hxf++foo49m//79qCrbt2+nVatWZa7/ww8/sGbNGnr27OlL/wBs3ryZWbNmsXDhQm677TZKSko499xzKSgo4P3332fXrl0sWrSoWv1kZBbneWbURjL9t0tmwcKrcMaLVqvqXhFpDgzPqFVpItED76qrrirzwFu8eHHCBx44s8gfffTRCjW7qkuzZs0oLCyMbe/YsYNmzZoxevRozjjjDNavX1/pcXl5eTHBvOyyy2KzwceOHRsTleqQav+ceOKJFBUV0b59ewoLC3nttdfKXD866TFZUu2fTZs20bVrV+rUqcNhhx1Gq1at2Lx5M8uXL+e+++4jEomwbt06Bg8eXM2eMjJFvXr12Lp1K82bN6/RnB8jOFSVrVu31ujLerIkI1AKHA+cDfwBaIAzHyr0pPrAA9i5cycXXHABEydOrOAhVJeTTz6Z22+/nYMHD7Jp0yYaNmxIcXExd911FxMnTmTUqFG8+OKL/OxnP2PNmjXs3OlMMVuzZg3HHHMMO3bsiE0QnD9/PscddxwAq1evZuTIkQBs2rSJUaNG8cgjj2S8f5555hl++tOfMnv2bNauXcvQoUNZvnx57Ljp06fz3HPP+dY/mzZt4pNPPqG4uJiioiK+//57WrZsyZgxY5g3bx6tW7fmoosusm/sIaJNmzZs2LABy8ytndSrV6/GWYVJUVUMEHgCeAxY6W43BZakI75Y01d1xqC6deumBw4c0HXr1mmvXr109+7desopp+ikSZP0/PPPV1VnjCU/P1937NihO3bsiI2x7N27V0877TSdO3eu5/VrkjE3efLkWFLCkiVLdPjw4Tpr1ixVVb311lv1scceU1XVOXPmxJIS5syZo6qqs2fP1q5du2rfvn319NNP13Xr1qVkU6r9M3HixNj4UGFhoR5zzDGxa3/xxRd68skn+9o/BQUFevrpp8fGoGbMmKGqqvfff7927NhRzz//fD3//PN12rRp1bbLMIzkwcckieVaLjECN7MvqFd1svhSeeDdd9992rx581hG2rhx41RVdeHChTpw4EA99NBDdeDAgfrSSy8lbU/YSKV/du/ereecc4727dtXu3fvri+88ELsunfccYc+8sgj/v9ChmEETroESrSKcIeIfIgziXaJqp4oIi2Bt1S1a0ZcuiTo3r27Ll26NKjbG4ZhGJUgIstUtXuq10kmi+8RYDbQSkT+CLwH/G+qNzYMwzCMyqgySUJVp4vIMmAgTjWJIaq6MuOWGYZhGD9qKqtmHl8n7wecibWxfapa+YpbhmEYhpEClXlQy3BSzKOTE6KDVeK+t4rjhmEYRsZIKFCq2s5PQwzDMAwjnmRWxj1PRBrHbTcRkSEZtcowDMP40ZNMFt9dqrojuqGqhcBdGbPIMAzDMEhOoLyOSaZEkmEYhmHUmGQEaqmIPCgiR7uvB3ESKAzDMAwjYyQjUDcAB3AWH5wB7ANGZtIowzAMw0gmVHeUqo7JuCVGKePHw0knwYABpW0FBbBkCbhrQBmGYWQ7yXhQj4vIRyJyfXw2X1YxfrwjAPEUFDjtQXDSSXDhhaU2FRQ42yedFIw9YeufsNljGEZGqFKgVLUPcBlwJM7qun8VkV9k3DI/CZsgDBgAM2dSMuxC1o78f44tM2eW9aj8JGz949qj8+c71fWDtscwjMyQbNlzIBc4H/gWWAmsAoamo6R6dV/VWW4jaebP10iLFvrtqJtVW7RQnT8//feoJi+ccaUq6L7f/T5oU1Tnz9eSFi208P+NCUf/zJ+vexs304dPvVgjYbDHMIwY+LgeVD7wEPAlzsKFJ7rthwPr0mFEdV8ZESgtFYTIbbdn5PrVYv583Vq/cagewH8//1pV0KIxIRBMVZ32iytUQTePvjVoUwzDiCNdApXMGNQEYDnQWVVHqupy1/PaCNyePl8uYAoK+PmCl/nzqRcjT06sOMbhsy1ceCG3Dvs9D/W5jF3PPFc2xBaQTd3mvsCfT72YupOeCtYW156zF/+NP596MU2emRy8PYZhpJ1kBOos4K+qWgQgIjkiUh9AVadl0jjfcAVh1HljeKjPZex77vlgBWHJEpg5k6VHdQGgqFc/ZwxqyZJg7HH7Z8xFt/NQn8vYOTVgwXTt+d9fj+WhPpexYeLU4AXcMIy0k4xAvQ0cGrdd323LHlxB+OA/OwOwv0/fYAXh1lvLJEQcjJQ420GlmEcFs53TP8X9+gfbP649nx3bDYDdp/YJ1h7DMDJCMvOg6qnq7uiGqu6OelBZQ/TB//c3ADgYUUcQgsqac4muc3IwUhKoHdH+iSx6q7QtyP5x7ZF/LgJANWB7DMPICMl4UHtE5MTohoh0A4oyZ1JwiKsIxSUBC0I5Dka06oN8IOLaoYTDnhz30xu2v5dhGOkhGYG6EZglIotE5D2ckke/qeokEXlTRDaLyO3udn8R2SQiC9xXN7d9qoj0TuF3SBvqPneLQyII4ipm4B6US8TtIA1H9yBE+yckBhmGkVaqDPGp6hIRaQ8c5zZ9oaoHk7j2VcDPgTZxbXNU9erqm+kvxSXheOCFJsTnUuIqU0lIFCrq8YalfwzDSC8JPah4r0ZVD6rq5+7roLv/MBHplOh8Vd3g0TzI9cQmiEh84gUi0lpE3op6Vh72XCsiS0Vk6ebNm6v8xWpCLMQXsgdeWAQzGkkLiTkxD/NAyP5ehmGkh8pCfOeLyGIRuVNEzhKRHiLSV0RGiMg04HXKZvdVxTLgZ+qUTtoJ3By3rz0wDbheVT2X8lDVp1S1u6p2b9myZTVuW33CEjKKeQjF4XgAR8d6NCwelPszLCFZwzDSS8IQn6qOFpFmOOWNhgGtcZIjVgJPqup71bmRqu6K25wO/F/c9l3ALar6TXWumSnCNugeFg8h6jmFRJ/IsRCfYWQ1lY5Bqeo2YJL7SgkRaaylS8efBnwRt/sa4EYR2aaqb1U82x+cQXcNTUgt6iOEzUMIzxhUuJJIDMNILxlbul1EJgGnAnki0h14S0RGAHuBLcCIuMN3A0NxsgXrquqcTNmVDGERhLAmAYRFv6MhvgMhCYEahpFeMiZQqnqNR/PjHsddGbd5VqbsqQ5hS5I4GBZFcAnLGFSOq+Dh8XgNw0gnycyD+tERFkGIpZmHzEMISffEOihsHqZhGOmhSoESkWUiMlJEmvphUBgInQcVMnvC4kFZiM8wsptkPKiLcNZ+WiIiM0RkkERHp7ONWKmjkDyAox5CSOyJEhZrcsQqSRhGNpPMku9fq+ptwLHAX4G/AOtE5G43DT17CFupo2gpn5B5CGHJ4ovV4guZh2kYRnpIagxKRPKBB4D7gJdw5kXtBOZnzrTgCMs8qLAWrw2LOVGdDFsI1DCM9FBlFp+ILAMKgcnAGFXd7+76UER6ZdA2/4kNuofDQyitxRcOe6KExYOKhmIPhKx/DMNID8mkmQ9T1dVeO1R1aJrtCQVhCxlZEoA3EVegzIMyjOwkmRDf1SLSJLohIk1FZFzmTAqesCRJRO0IXYgvLB6UK0xh+0JhGEZ6SEagzlDVwuiGqm4HzsyYRQFSWnw0HA+84piHEA5BiBIS/bYQn2FkOckIVK6I5EU33GUy8io5vtYSfcyFxYOKhq7CFsIKiwdlIT7DyG6SGYOaDrwjIlPc7eHAM5kzKXjC4rFE093D9gAOiT6FVsANw0gPyayo+ycR+Scw0G26R1XfzKxZwRC+EJ/7AC4OiSK4hKWSRNSDCsu8NcMw0ktSxWJVdS4wN8O2BE6YQnyqGvPkDgaQJLHvYIRl67bT65gWFfaFoHuA+DGocHyhMAwjvSRTi2+oiHwlIjtEZKeI7BKRnX4Y5zeREGXNReJUIIiQ4/1vfsGvnv6Qf24orLAvLGNQYQ2BGoaRHpJJkhgPDFbVxqp6mKo2UtXDMm2Y36hqTBS27DrA04tWBxrKivfiggg5bt1zAIAvvnMWQv7ZbW/E9oVEn+KyHE2gDCMbSUagvlfVlRm3JGDivZQXlv6bcXNW8v7qrQHaU+L53i9aN64HwMbCfa4Npf0TljGoqKe7fc9BHnzrC5vQbBhZRjJjUEtF5AXgFSBa5ghVfTlTRgVBxGNgZfuegwFY4hA/8B/EPJ+WjZyZBJt2FLHvYKTMvrCMQUXcflmxaScrNu3k6FYNObfLEQFbZRhGukhGoA7DWab99Lg2BbJKoLwSEXbvD06g4u05UByp5MjMEF3K4tvColi4L0poxqDKKWW2rgJjGD9WkkkzH+6HIUHjlaq8fW8wAnUwUsIf55RGVQsDsCPqUW4sLGLzrv1l9oVDnioms+zdXxyQJYZhZIJksviOFZF3RORzdztfRG7PvGn+4pW598PO/R5HZpbl67fzs9vm8rdPNgJwSG5OBQ/GD6Je0jeb9/DDzn2e+4KmuEQ5plXD2Pa2vf73k2EYmSOZJIlJwO+AgwCq+k/g4kwaFQReHtQPu/Z5HJlZ1m7ZU2a7QV4u2/YcoMTngZ94EfpwzbYy+8KQJLHvYARV6Hh4aUJpEJ6mYRiZIxmBqq+qH5Vry7pYirdA+e9BNcgrG3XNq5NLpETZUeTvwzdeD99Z+X3ZfSFIlmt/xzwAjmoR50EF4GkahpE5khGoLSJyNO7Qg4hcAGzKqFUB4BXi+26H/x5U1Dv5v6EncP+wzoz+xc8A6HrP39nu4wM46kHlCKzduresjb5ZUTV5dXNYe+9ZdDz8MF/7xzCMzJNMFt9I4CmgvYh8C6wBfpVRqwLAq7zRt4VFHIyUUDc3GR1PD9EpTyce2ZTj/qMR//h6Sxl7mjY4xBc7oiHF/2zegDXlwo5hGYMCqJPjZO41a3CIjUEZRpaRzJNXVfXnQEugvar2TuY8EXlTRDZHEyrEYYKILBKR10Wkmds+VUR6p/JLpAOvybCREuXb7UW+2hF9+Ec1sXnDUkGqk+tfGnVUr49sVh+Adi0axPaFYQwqSnSOVtP6h7B51/5Q2WYYRmokI1AvAajqHlXd5ba9mMR5VwG3xG0PwhnP6gPMBG6tjqGZJppW3dAdA2pavy4Aa7fuSXhOJogKVHROT7M4j8nPsZ+oHT9tdigAA9u34ukrugPhKXUEsNENw+a3acyG7UU8tXB1wBYZhpEuEgqUiLQXkfOBxm7B2OjrSqBeVRdW1Q3lmvoBr7vvX3O34+/XWkTeEpFuCey5VkSWisjSzZs3V3X7ahMVqFaHORUUOrR2ssPKh7cyTcyDcgWqZcM8jv1JwzL7fLHD7Y/6hziC3fjQuhzZvL5rh29mVEk0Bf6q3u1o3bgeX3y/q4ozDMOoLVTmQR0HnA00Ac6Je50IXFODezUHtrvvC4GmcfvaA9OA61V1mdfJqvqUqnZX1e4tW7aswe0rJ/rQ/UkjR3tbNMyjdeN63P/mF74mS0QjjdFKDiLC//yyvbvPR4FSyM0R6h+SC8Chh+TiDveEYgwq6ln+7swOgNNPdXNzfE/HNwwjcyRMklDVvwF/E5FTVPX9NNxrG47YATSmVKwA7gJuUdVv0nCfGhF96P7E9aD2HojwuzM7MOr5j1m9eTf/0bhKpzE9drgP2Jy4rw45rjL46kGpkiOOZ7JrXzGXnnwkm1yhDoNA1ckRLj7ppxzdsjTNPDdHsLULDSN7SCaL72MRGQl0JC60p6ojqnmvd4HzcIrOnuluR7kGuFFEtqnqW9W8blooDfE5v+Ke/cWxit4Rn4UBSj2o+Pd+CkNEFRGhUb263HH28UDpisNhoEQ1JtxRRMIhnoZhpIdkBGoasAonyeEPOCnmVS6/ISKTgFOBPBHpDgwFzhaRRcBO4Iq4w3e7+2eJSF1VnVOt3yINRD2XpvWd0NHeA8UxYfAztBaJZfGVPnxzY3b4ZgaqpfeNEoRQJqLEw75cEQvxGUYWkYxAHaOqw0TkXFV9RkT+Ciyq6iRV9RqnGulx3JVxm2clYU9GiD7XWrhp3S0b1YuJhL+hNednGQ8qJ7rP3ySJcg5KqUCFoJJExMO+3Bzx9cuEYRiZJRmBitbYKRSRTsB3QKvMmRQMUc/lqJYNeOzSE+l1THP+vc2ZA+Wn5xIbg4p7+JYKg7+eXI5UDKFBSDyokoohvhyRUNhmGEZ6SEagnhKRpsDtwKtAQ+COjFoVAKXCIJyV3xpwKjeA/8kJUC7E5773cyxMFc8xHghHqaMS1YohPvOgDCOrqHKirqo+rarbVXWhqh6lqq2ALVWdV9uIPtjihSEQz6Wk7ETdMnb4+OyNZvHFE7UjDNUaIh5JEjkSrjlahmGkRk2LzD2UVitCQMQjey4ozyX+3o5Nzk+/hbJ8iC8IoUxEiVLRvhwL8RlGNlFTgQpTxnFaUI/QWpBZfPHOQUwofZ6o6+WhOPuCFwGvJI5csRCfYWQTNRWorHsKlK/gAASSxRcpqejJBZHe7SUA0a8lIdAnIqplvkyAI6gmUIaRPSRMkhCRz/AWIgF+kjGLAqJ0/lFpWzDzjyoZC/M5WSPRPKigx6BU1Uni8JgHZQJlGNlDZVl8Z/tmRQgo8fJccsru84PKPDlf0921bKJGvE1Ba4DXXDFw/l4HrNaRYWQNldXiW+enIUHjlcUXRJJEiecYVNl9ftmRUy4AHJYxqNK/Vdn2HPOgDCOr8G+p2JDjVQMvN6DQmkhZ70VCEuIToiE+38zwJPa3KjcGlWtZfIaRVZhAuXg99GJVxH3NnvOYgBpANqFXGrcE4Ml54fVlAmwMyjCyDRMol+j4Tq6HB+VrmnmJx4M3iDTzEqWcGXFJEr6Z4UksxOc5DyoIiwzDyAQ1EigRGZtmOwInNv8ofh2mqED5XcGh3F8lVmLIZzsqpHHHSh0F7UE5Pz0rSZhCGUbWUFMPynPV29pMLL074Cy+khLvGnPgf7JGhRAfIcni8yioC9EFC02gDCNbqJFAqepr6TYkaLwmyAYhDF5VxIMKNZZPMw9LNXOvNbPArWYetHoahpE2qqxmLiKPeDTvAJa6y8JnBTGBCrjUkVcV8ei2nxNkVdUzjdvZ55sZnkQFsryAmgdlGNlFMh5UPaAL8JX7ygfaAFeJyMMZs8xnKlvmwv8irWXbghBKrxBfbAwq6Cw+j4SW6HbQ3p1hGOkjmfWg8oFeqhoBEJEncFbU7Q18lkHbfKXSLD6/5x+Vn98TQLJGxKOSROl8LP/s8KL0y0TZdhEJxWq/hmGkh2Q8qKY4ixRGaQA0cwVrf0asCoASryy+HP8fyM5E3YolfCCAEF8FT875GbSX4rVmFjiCZfOgDCN7SMaDGg98IiILcArF9gX+V0QaAG9n0DZf8arFB251Al+z+Dzm94QkxBc6D8rGoAwjq6lSoFR1soi8AfRwm36vqhvd97dkzDKfiSR66Im/D72Ix0q2gWQTllRcsRZcLyroMSiPRR3BsvgMI9tIJovvNeCvwKuquifzJgVDiUcWn7Pt/zyoihNQ/c+ec0odVWwXCb5aQ2mIr2y71eIzjOwimTGo+4E+wAoReVFELhCRehm2y3e8FsAD/ytkV1bBwd9094ohvqgtQYuAV8YlWDVzw8g2qhQoVX1XVf8bOAp4ErgQ+CHThvlNIo/B/xBfOGrxRUq8BTsMHlSiMaicENhmGEb6SCZJAhE5FDgHuAg4EXgmlZuKSBHwobs5DYgAbVR1XCrXTQVniXMPj8HvJAmPMSgRQcTfLD6vBQvBEfGga/FZFp9h/DhIZgxqJk6CxDzgUeBdVU11tsm3qto/7h5Xpni9lEnkMfidGZZQKH325LyEEpx6fEEP88Qm6npU3LAsPsPIHpIZg5oMHK2q16lqAXCqiDyW4n3/Q0TeFZGXRaRttFFE6orIVBEZnuL1q03EYx0miI5r+GeH1xgURNc68tmORGNQAXspiSbq5ogEXuXCMIz0kcwY1JtAvoiMF5G1wD3AqhTv21ZV++GMaU122xoBs4CZqjql/Akicq2ILBWRpZs3b07x9hXxqoEHzkPQz4eeV5FWcLIJfQ3xJbIjBOM8US+pQojPkiQMI6tIKFAicqyI3CUiq4AJwL8BUdUBqjohlZuq6hb355vAf7rNlwLfqeobCc55SlW7q2r3li1bpnJ7T7xq4IH/D70SjyKtEEw2oXeaefBjUF5Lo0DpgoXmRRlGdlCZB7UKOA04W1V7u6IUSfWGItJQRHLd9/nAFnfXk8BeEbkj1XvUhIRp5n6PQSUIrfmdTZgo1CgS/BhUNNSZaFkSc6IMIzuoTKCGApuAAhGZJCIDAY/v1NXmeGCpiCzE8cz+K7pDVW8C6ovIPWm4T7VIlJzgd6mjSEnFWnwQRDZhRQGAcMyDKl0apWx71PO0MJ9hZAcJs/hU9RXgFbfm3rnAjUArt5r5bFV9qyY3VNWPgK7lmj+N2/+7mlw3VRJm8Yn4WkVctWJ2GkSFwT87Skq0QqUGx47gqzUkCvGV1go0gTKMbCCZJIk9qvpXVT0HZx2oj4H/ybhlPpPIYxCfs9YSjoUFEWoMa4gvVnnee0KzCZRhZAfVWvJdVbe7yQoDM2VQUJSoVggZgSsMAVcRB/8LoVYq2EELVKLK8wFUfTcMI3NUS6CymUhJJfOgfJ8gm2AszOdq5t4hvuCz5KK395qoC9iihYaRJZhAuUTUe3kJ39eDSjgG5e9EXa1k4nLQEbRSD6pse3SBRasmYRjZgQmUS0kCDyoIz8VzHaYcf8dWEob4CH6MJzYG5TEPCoK3zzCM9GAC5VLZ2I+fWXyJJsjm+pw9l8ijDEM181gWX4J1s4IuxWQYRnowgXKJlCQqdeR/NfPENQH9Xg+qYrvfJZe8SDhRN4CVhw3DyBwmUC6JSgz5XeoocS0+fz2oxBN1JeBCR4mLxVoWn2FkFyZQLgmz+HL8/UaulQiln9lpCRcsJPgxnuj9ywu5ZfEZRnZhAuVSEpIsvkiCkksi/gpliVZWScI3MzyJekgVV9R1fgYtoIZhpAcTKJfKkyR8ngcVAqFMVJtQQlCLL9oN5T08G4MyjOzCBMqlsom6Yajg4He6e2XzsYIehIr+Pcp3k2XxGUZ2YQLlUlJSsTo2+F8DzxHKiu0SQLq7V4gvDB5UJEGauXlQhpFdmEC5JFwPyufkhIQhPp+L1lZaEzDwEF+iMShLkjCMbMIEyiVxDTyfKzhUti6V3yE+zzGo4JMkSkN8liRhGNmMCZRLZcLgbzXzxMIQhiXfnWKxvpnhSSyLL1GIL2gFNQwjLZhAuVQW4vN1DCrRsh8+htZUFVXvCcMSgmrmsSy+BPOgbAzKMLIDEyiXSEkl2XO+lxhKFOLzx4ZEadwQrjEoSVBJwrL4DCM7MIFyKSmppNSR39XME03U9enBGxUArxBfKMagEiRJlK6o67tJhmFkABMol4RZaznhKDHkZ5JEbL0lTw8q8GlQCYvFRjdtDMowsgMTKJdEy0vk+Oi5gJOA4Bni8zFJIqqDidaDCn4MKiqgZdtjIT4bgzKMrMAEyqWyBQt9T5LwXObCzzGoxCG+UIxBJajFZ1l8hpFdmEC5VJbF56fHUJLQDv8G/xOtWBttC9pBqWpFXcviM4zswATKpaSSLD5f5x8lWA/KT09OE4zxQDhKHZUkGCOLelRBhyANw0gPgQiUiFwpIotF5B8icqK7fXsQtkRJPDHV/wmyXtmEfobWKs/iCz5LrtJCtpQmURiGUbup4/cNRaQpMAroCRwBTAOers41/r19LzfP+pRckbiBcollcQnOg1QQ954QfZxFvZPSY53zdhQdTJg9V3Qwwh/nrKiOiTWmOEGaeY4IW3bt98WOooMRILEIrNmy27f+8OKjtdsTLkcP8MKSf/PRmq3+GmUYRtrxXaCAHsAiVT0ArBGRRkAegIjUBSYB76rqlEQX2LM/wuKvtxBxKx4o0cwz56t9aZu7TWlmmqoSd2jsOAE6HtG4wr06Hn4YeXVymf7h+hR/7eRolFeHDq0Pq9Ce36Yxb6/83jc7Gh9al2NaNarQfsIRjfl4faFvdiSiy0+bVGg7vPGhHN64Hou/2cLib/y3yTCM9CJ+x+tF5FLgWFUd626/C8wDmgDHAU+p6hse510LXOtudgI+98PeNNIC2BK0EdWkNtoMtdNus9kfzGZ/OE5VK37DrSZBeFDbcMQoSmO37b+BOV7iBKCqTwFPAYjIUlXtnmE704rZ7B+10W6z2R/MZn8QkaXpuE4QSRIfAr1FpK6IHAnsBvYDTwJ7ReSOAGwyDMMwQobvAqWq24HHgXeB54Eb4/bdBNQXkXv8tsswDMMIF0GE+FDVvwB/iWtaGrfvd0lc4qm0G5V5zGb/qI12m83+YDb7Q1ps9j1JwjAMwzCSwSpJGIZhGKHEBMowDMMIJaEVqPLlkCo57pci8r77GuSnjXE2JGWre2wzEdkmIpe52yIiE0RkkYi8LiLNwmSziPxORJaIyEciclNc++/dc+eLSNsw2Zzuc6tLNfr2LyKySUSeLtdeoW9FpJ6ITHc/J9NFpF6YbHb3DRARFZE27nYz9zO9yP2Me9T/CM5uETlERGa69n0oIqe57aHva49jffl/TLG/RUReEpEFItJDRP7HfW5fm+g6TmWFkL2ApsBy4BCgHfBeguNygX/izKtqAnwK5IbR1rjj7wNeBy5zt38JTHbfXwHcGxabgUbAV24/1wG+BBoA7YG33WP6AjPCYnO6z82knTilvvoDT8e1efYtcB1wh/v+TuC6sNjstgvwGrAEaOO23Qtc7r7/C/DLkPX12cAU931b4MPa0Ncex/ny/5iG/m6NUyUour2SKp7XYfWgYuWQVHUN0MhV2zsBROQZERkKHAOsUdVCVS0E1rptYbQVceZ9tSYuaxHohyNY4PyD9wuRzUXARuBQ91UEHHRtnAOgqguBziGyGRH5k/vNrEAcr9rr3Lyg7VTVbz3OT9S3mfycpGozwDDgTWBPud8lk5/tVO3+BshzPbumwA8+2J2Sza7X9xfXuysQkc749/+Yan8/BeS7HtRdOF8K3hGR3oluGFaBag5sj9suBJ4FeorIw8AeVX05wXG+hMjiSNZWgLuAP1ZyfiHOP0qmScpmVS0G3gC+wPGenlKnhmL583PDYrOInAn8FDhVVQcAbyc4N1Ofk+p8HpI5P9ejvZD02p+SzeLU0LyaiqnFzdxrRa+Z7j5Pta9X43zxWoVTbi06/zK0fY3Tz9+rah/38/25xzUz9f+Yqu03AMtUtb+q3g18675/L9EJgcyDSoJE5ZAeAuYCR1ZxnJ8kZauInACoqq4sF4qPP78xZT8AmSJZm48FzgeOwvky866IvOJxfiTTBnvcM9FnohNQoG4MQVUjIuLn5yRZO5M9P+LRnm77U7X5WuA5VT1Q7rO93b1WIZnp81Tt/jXwb1U9zx23eRk4kXD3dSdgdnQjwec7U/+PqdpebcLqQXmVQ6oD3I0TH37EPe4roJ2IHCYih+HERb8Oqa3dgONEZB5wGXCLiPTAqahxpnvMme52WGwWYJeq7lfVIpySVA1dG88AEJFTccb+wmLz58SFZEQkx+tcVd0fsJ2JSNS3mfycpGpzJ+Ay97OdD0wTJ7Eg05/tVO0WSouwbscZc4Vw9/XnOGM7QOzz7df/Y6q2V59MDKalaUBuBLAY+AfQHWeQ9QJ335+A/3bfnwm8777ODLOtccePpTRJIgd4DFiEE0duHiabgf8DPsD5cN4bd/4d7rkFwFEhs3m8+3mYDwzyOjckdo4DlgHf4oQiGyTqW5xQ1PPu5+R5oF6YbI67zgJKkySau5/pRe5nPCdMfe2+XsV5wC8BLgx7X+MkKEwB3nM/3138/H9M0fa2uMkc7jFfV3U/qyRhGIZhhJKwhvgMwzCMHzkmUIZhGEYoMYEyDMMwQokJlGEYhhFKTKAMwzCMUGICZRjVREQiIvKJiHwuIrNEpL7bvruK864UkUerea+pInJBKvYaRm3FBMowqk+RqnZR1U7AAZxJioZhpBkTKMNIjUXUoECx6xk9Is7SBaujXpI4PCoiX4jI20CruHO6ici7IrJMRN4UkdYi0tg99jj3mOdF5Jp0/XKGESQmUIZRQ0SkDk6Jmc9qeInWQG+cZR/uddvOA44DjsdZfuVU9151gQk4s/a74czg/6Oq7gB+A0wVkYuBpqo6qYb2GEaoCGuxWMMIM4eKyCfu+0XA5Bpe5xVVLQFWiMhP3La+wPOqGgE2ish8t/04nJp3f3cLsuYCmwBU9e8iMgynnJAfS58Yhi+YQBlG9SlS1S5puE58wdqqVpsV4F+qekqFHU7B0A7AXpzlWjakwTbDCBwL8RlGuFgIXCQiuSLSGhjgtn8BtBSRU8AJ+YlIR3ffaJzVSS8FprjhQMOo9ZgHZRjpo76IxHsvD6rqg9W8xmzgNGAFsB6nKjvqrLV0AfCIiDTG+d99WESKcRax66Gqu0RkIXA7zuKYhlGrsWrmhmEYRiixEJ9hGIYRSkygDMMwjFBiAmUYhmGEEhMowzAMI5SYQBmGYRihxATKMAzDCCUmUIZhGEYo+f+iFy/1d5LvNAAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 432x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Demonstrate the load->store channel (i.e., VPN extraction)\n",
    "# Correspond to Figure 6\n",
    "\n",
    "def plot_vpn_latency(step=2000, **kwargs):\n",
    "    name = 'vpn_latency'\n",
    "    lats = run_bino(CORES, name, **kwargs)\n",
    "\n",
    "    offsets = np.arange(0, 0x200)\n",
    "    peaks = peak_seeking_std(lats, 4, reverse=False)\n",
    "    fig, ax = plt.subplots(figsize=(6, 3))\n",
    "\n",
    "    ax.plot(offsets, lats, label='Latency')\n",
    "    ax.plot(offsets[peaks], lats[peaks], 'rx', label='Victim PL Index')\n",
    "    for _, peak in enumerate(peaks):\n",
    "        ax.text(offsets[peak], lats[peak] + step // 2,\n",
    "                f'{offsets[peak]:#05x}', ha='center', fontsize=9)\n",
    "\n",
    "    ax.set_xlim(offsets[0], offsets[-1])\n",
    "\n",
    "    max_y = np.ceil((ax.get_ylim()[1] + 3000) / step) * step\n",
    "    ax.set_ylim(0, max_y)\n",
    "\n",
    "    ax.set_xticks(list(np.arange(0, 0x200, 0x40)) + [0x1ff])\n",
    "    ax.set_xticklabels([f'{t:#x}' for t in ax.get_xticks()], fontsize=9)\n",
    "\n",
    "    ax.set_yticks(np.arange(0, max_y + .1, step))\n",
    "    ax.set_yticklabels([f'{t / 1000:.0f}k' for t in ax.get_yticks()], fontsize=9)\n",
    "\n",
    "    ax.set_xlabel('PL Index', fontsize=10)\n",
    "    ax.set_ylabel('Avg. Latency (cycles)', fontsize=10)\n",
    "    ax.legend(loc='upper right', fontsize=10)\n",
    "\n",
    "    fig.tight_layout()\n",
    "    fig.savefig(RES_DIR / f'prim_{name}_{platform}.pdf', bbox_inches='tight')\n",
    "\n",
    "plt.close('all')\n",
    "rebuild()\n",
    "fig = plot_vpn_latency(step=5000, iters=1)\n",
    "plt.show(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ninja: no work to do.\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAADQCAYAAABStPXYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAABIuElEQVR4nO2dZ3hU1daA3zVJSCCBhBI6mAAiNfSOAjYUVATFcu3Y9VrvpxcvKhZU7AV7xY6iWJFykdAuLYAg0nuHhJBKemZ/P87MZJLMhEkyM+ck7vd55pk5fc0pe51V9tqilEKj0Wg0GqthM1sAjUaj0Wg8oRWURqPRaCyJVlAajUajsSRaQWk0Go3GkmgFpdFoNBpLEmq2AFWhSZMmKi4uzmwxNBqNRuOBtWvXHldKxVZ3PzVSQcXFxbFmzRqzxdBoNBqNB0Rknz/2o118Go1Go7EkWkFpNBqNxpJoBaXRaDQaS6IV1N+MncnZZOcXmS1GrWTtvjTyCovNFqNWknaygKS9J8wWQxNktIL6G1FsV5z7ymJu+TTJ6zrzNx1lwvQkdI3GynHgRA6XvbOcJ37eZLYotZIJnyYx/t0VFBTZzRalSqzdd4IHv12P3R785yqvsJhlO45TVGxn4dZjHp/t49n5lny50goqACil+Gn9IdMsleW7jnPGo3M4lpkHQOK2ZJ6bs4UtRzIBWLnb+5vobZ+vZeHWZI46ttX4RnJWPoB+yw8Qfx3KACD1ZL7JklSN2z9fx6x1hziUnhuQ/afnFLie77I8/tNfXPvRKm7+dA0Tpq9h2c7j5dbpO2UBF01bxpGMwMhXVbSCCgCbj2Ry34z1/GfWRlOO//L87eQX2Vm+y7gRH/l+I+8t3s20hTsq3O7pXze7fr84bxtpJwsCKmdtIiXLUOjFJrwh13b2p+ZQWGyc15SsmqmgwkONpnbP8ZN+3/eh9Fz6TlnAha8vZevR8kpq6Q6jHVi8PQWAvWVkcN6zO5OzGfTcQvKLKrakcgqKSl2HzYczufr9lQx/MZFv1xyo1n8pi1ZQAeDAiRzAiEkEk583HKb/Mws4mGYcf/PhTGb/ecRlDc3bdMzjdjuTs+j/zAI+WrbHNW/WukO8lbgz8ELXcJ6fu5WFW49xNMM4x0VBUlAZOYVsOpwRlGOVJVBWgDfOejHR9buyCmp/ag4Tv//TVNfgiZMFiBi/fVVQhcX2Cv/roz9upOOkOTwyayMzVu933XfvLNpVbt30nMJS07tSSsuQllP6RXRfak6Fsl330Wr6PbPA5SqcvnwPK3ansjc1h6d+2VzhtpWl1iuob5MOMPH7P11KoyokbksmcWuyz3EZ5w1w4mRBUGM5/5m1keSsfI5lGjf2B0v3cPdX6wBo3bCu1+2+W3vI5aK6sm8b1/zGUeEe11+yPYVBz/1epYYqv6iYw+m5KKVcFprdrigosrPjWBYfLNlNsV2RV1jMiSpYcNn5RT672ZZsT2FnchaFxXaf/e8rdqVyzYcrKSiyk5FTyDuLdjFh+hqOOc5f2f0UFNnZmZxdal5RsZ1jmXkcy8zjzYU7qmR1jXvnf4x+Y1nQ4wZv/L6DIVMXMvevo0E5XlnFklxJBTXpx43MSDrAmn1Vc71m5RVW6RwXFNn5fOU+DpzIoffT/+VgmvGsnEpB7TiWRVZeIWe9kMjgqb+TkVtYbp1jmXnMWH2AgmI7X6/ez7SFOxnaoQlX9m3DT+sPM+7t/7mspN+3HCPXTf6wEGG3Y1lBkZ3s/CKOZxvn9Paz2gGUu1/L4nzx3u9oU49klIQDGkXWqXDbylIjK0n4SkGRnSd+2UROQTGNo+pwXpfmnNaoHg0rcRKL7YqbPjGSCl4a34OvVu2jY7P6PDu2OzabeNxmt0NB5RYW8/nKfYzr3ZqocO+n2m5XfJ20n5Fdm/P8nK2M7dWKwR2alFtv2Y7jJG5L5p8jOrBufxqvLdjBxzf2Y9a6gyS0jikV8+rROpoNB0vesK8fdBrP/rbVNb1oWzI2Ec7qGMv6A8YNN/niLtw0JJ7UkwUs2HKMenVCPMp60/Qkiu2KXzYcZl/qSTYfzuTbOwYRHlp6/WK7Ij2ngMZR4Sil+McHq1i7P42CIjtTx3Vn4qyNvH1Nb/YcP8mL87a5tmsRE8G8Tcf4ZcNhNj81km+SDhAVHkr31tG8v3g3l/dp7fH8AEyYnsTqPSf44a7BfL16P49f3JWiYjuH0/Po0rIBYDyASimu/3g1oTahdcO6NK0fwTe3D0TE8zV1MumHjew+fpIlDneJk0OOBuh4dgF5hcVEhIWQV1jMs79t4bMV+1j68AjaNKoHwGsLdvCmm3Xas01Dhp5u/J/5m47y5C+bmf/AWUSGh7LtaBZNouq4XhaK7Yqr3l/hegn6Y386g9o3rlBmd3YmZzP3ryOM6dmKljF1CfFwDyulSp0HpRRTZm/hu7UHXQ3mkh0pXNCt+SmPN/mnv7Arw7I8mJbDpsOZzLxjEO1jowBYfyCdLi0aUCfU87ty2ZhTZS2ofIeCK2tFuLPhQDrNGkTQPDrCNe9/O4+TV1jMv7/fSP2IUD6+sR8CNI+OICKs/HPhZF/qSUJswuM/bWLh1mQGl7k23uJEYLjgbvh4Ne1jI12N/tp9Jzi7U7NS683+8whFdsUPdw1m7NvLARjcoTEto+vyzZoDrNufzoPfrueTm/rzr5kb6NaqAX8dMo57fpfmrD+Qjt2uuObDlazZl8ZFCS0BGNi+Me8t2V2hgjrmFpteuy+Nto3qsfFQBpf1bk3z6HDeXrSLnAL/xd5rlYLKKywmxCas3nOC6LphXDRtmWvZvE3HeCvRMH//fUEn4pvUY2C7xjSICPOqaKAkOAvwyKw/KSxWrNufziU9WzK4felGsqjYztO/bub7dQddN8XjP23i8Z82MaxjLC9ensCO5GyGdGiCUoonf9nMku0pNIkKZ/XeEzz962byCu388Mchdj47qtS+7XbFhE+TKCiyU1hs57MVRiWRCdOT2HiovKvn/vM6uhTr61f1ZHD7JqUU1I2OZRMv7MS6/elMGBLPTUPiAXhpfAI9n/ovdi/ZPs43/qlzSva3YHMyoxNacDw7n8d/+ovHL+rK7I1HePrXzSz81zDyi+ys2J3qWv/Z37YARgC3VUOj4R7XqxWzNx7hvcW7Xf/poe/+ZPafRwDo2SaG9QfSOZFT4FFB5RYUs3qP8aZ8++drSc7K51B6LnuP53A0M4/f7j2TpTtSmDJ7S8k1syv2puawNzWHGz5Jon5EKE9d0pXGUeEcOJHD16v38+B5HQkNMRrQJvXD2X38JLd8VrrU1s8bDrt+93tmAZf0aMnCrcmuhmbWukP0Oa0h36w5wC9u6wK8umA7feMacjw7n3tn/EFeoZ23EndyRd82jHxtCQCPju7Mmr1pzN1kWC51w0LILSzm6g9WcnGPlpx1ehPGO6xfpRRfrtrPzuRslu5I4d5zTqdenVB+/fMw8zYdJa/Qzkvzt3Nu52bUCRW6toymW6towkKEVjF1ufnTNexMzmZAfCPaN43iq1X7XbI2iAilTaN6rPPivj6Unstr/91OkV1xNCOv1DUPtQlFdsWo15dyx7D2NI+O4JFZGxnfpzUvju/hcX9lFdKxzDyOZ+fTJCqcjNxCdqdks3L3CVbtSSU2yrg2Ey/sRL+4RgA4n2ynByVxWzJN64fTtWU0drti7f40xr+7gph6Ycy97yxW7Unl5/WH+X1rsuuYx7PzGfHSIgBGd2/By1f0IDzUVu5lJjU7n4umLSMrr6SBXr4rtdQ6q/ac4ImfN/Ho6M6ue8rJH/uNc7or5SSdmtdnV0o2by7cyXdrD3LdwDjyCos5mpnHHwfSaREdQa+2DV3bJrSK4fRmUa7pdfvT6fHkfAA+nzCAb9ccYEdyFv3jGzF74xFu+GQ1SXuN4znvxzYN69Eqpq5HBXUkI5fv1hyksLjEon3w2w08Mmsj+UV2BrdvTGR4KErh2q8/qBUKqtiuuP+b9Szelkz/+MYs2FISa2kSFc4F3ZrxxcqSh+z5uUbD2i42kpz8YkZ2bYZdwXldmnFWx9L1DZ0P2EMjzyj1lr/hQEY5BfX71mQ+XbGPvqc15I5h7dl6NJOX5m8HjLej/s/+DsCUS7sx+edNFNsVTRwPFUBeoXHxixwurlf/u53bh7WnUWQdkrPyXe4Op3ICPCongLNOj0UEbhgUx5ierQAQgbI6Z+qcrdSPCOW6Qae55onjsfbkeXK69To2i2L7sWzXfn/44yAN6oaydMdxftt4lKy8IqLrhgFw9suLy+0n0/EQH88u4Hh2AXcOb8+/L+hEt1bRPOWWrOFUTmC8bQMs2pbCsh3HXVaHk23Hsly/na6g/+1MpUlUHcJCxNXYO4mtH05KVj6jE1qwfn+6yyqKrhvGs2O78/6S3Xy+ch9nd2rK1qNZ/PDHoVJxxd5tY+jYrD7Ld6Wy/0QONw6OY/ryvWTlFfGlW6MOhhJy5+Mb+1JQpPgmaT+J21I45+XFpVymby/axdtu8QSnUq0bFkKrhnWZd/9Z3P3lOjYdyeCXDYf5beMRCortpOcUsnhbCqvd3Jz3zVjv+t0iOoK7R3Rg0bYU13Py20bP7rpVe06wyqHwo8JDWfHI2eQV2pmxej8v/3c7T/y8iYHtGnEwLZdebWOIDA/lho9Xu1zMTprWD+epMd048/QmzPnrKO8t3sXrv5ck7Mxce5AQm3AoPZd2TSIZ06sVvR2Nb1kF9eWq/Xy5aj+nNa7H8ax8ThaUd7+Nf3cFL1yeQHTdMJf8B9JySNyWzITpSdQNC+HJS7pyIC2XNxxypOcUMvC530vtZ8KQeG49K57kzHzGvPU/AGZvPMKCLcdoFxtFr7YxLN6WwmMXdebjZXtd57x32xiuHXgaoSE27v36D9f+zuoYy5LtKUxfvpeLe7Skz2kN2Xo0k8g6htLffDiTdk0ieWpMN1o3rMu/v//TJX/Za3RhGeu1W6sGxNSrw4zbBnJa43oMem4hNoEPb+hL99bRdG8dDRjKdvLPm1i64zjXDGjLZX1aM85hhTWJqkPbRvU8uu6/TTrouoeHdGjM4PZNeHHeNvKL7MTUC+PiHi0pLLbTplFdvyaH1VgFlZFTSFiokJlbxNO/bmb2RqMhW7DlGP3jGjHsjFgu6Nacto3qseNYNrP/PELjqHAGt2/sauBTsvLJyiviU8d0Vl5hOQV1PCufyDohnN+lmUtB1Q0LcbnF3Fm3L406ITa+vHUA4aEhnNulGXeP6MDyXalc8+Eq13qP/vgXAK1i6vL7v4Zx15fraNuoHtOX73Wt8+K8bXy0bA9hITZW7k5ljaNhnDSqM8/8toUmUeG0bVSXdfvTXdu8dmVP7EoRFmIjxCZsn3IhoW7W4R+PnUfqyQLOcSiMRy7sxAdLd/PWP3oT3yTStZ44Xuw8xc+cFsHIrs3ZfsxwU53XuRnzNx9jwZaSt87/7TzO8DOaltvenbjG9djrCMgOdVhEY3q2dCko5/KhHZrw58F0MvOKuGVoPB8u28O1H61iw+TzaRARyvUfr2Zfag5ndzKO16xBOMcy87lzeHsGxDeiS4sG/G/Xcf79/UZuGhJHbFQ4U2Zv4clLuhIRZmNw+ybsTjnJO4t3cTAth69W7WfdvjSXkvt0xT4WbC7x5fdqG8PjF3VxvcEey8zjj/3pnN+lGa0b1mXP8ZNclNCSdrGRzN90lP7xjfnnV+to06geL16egIi4fPXDz4jl+blb+eR/JdceoF2TSLq1iqZRZB1i6xsu0k7NGzD09CYU2RUhNuHd6/oARmr7+HdXMOkH4746vWkUI7s2K5cUc+PgOP55dgeaRIXzj/5tafef3wBo3iCCe885ndYN6/K7Q2ldNyiORpF1eGb2Fi7t1ZL2sVHUjwijfgRc2b8NL/93O9OX7y11zzZvYLjIfr1nKF+t3k9840jaxUZyTucSF9XlfVpzWe9WrD+Qzti3l7teEmYkHaBOiI2lO46z/Vg2X982ECitoE5rXI9m9SM4lJ5LVHgoA+IbcUbzBvRsE0Pz6AiGTF3IuN6t+G3jEWatO1iqO8VXq/bz0/rDnNaoHkcz83jouz/L3Y99TmvIvy/oRJtGdbEr4/kEaBFdl/oRoS7LKL/IzpYjmS533R1fGHHekV2bcV6X5lzepzVgvDhvPpxJanY+LWLqcvOQeL5bd5Cnf93MjmNZ9GwTwwWvLQXgg+v7svlIJj3axLhevN65tg+5hcXc9cVaNhzM4Kp+bVizL42dydn0ahsDwJv/6MXibSnE1DPup4HtDJfiggeHERsVTnS9sFL/sUlUOJMv7kL9iDAu79O6VPyzQUQYTRuEs25/+bbtmCNLdeKFnbgooQXNGkTQumFd4hpH0iiyDnVCbdQJtfH6Vb0Y/+6KcttXFamJHTI7de+pii5+lnp1Qlxv4jcNiePHPw6RllPI1qcvKOcndl6IEJuwcOsxmkSFu9wEq/ecYPLPm7iqXxumXpZQarunf93Mt0kHWD/5fNo7HuhLerRk9Z4T3H12B6b9voMr+7WhQ9Movli5z+EbHlJO5lf+u53Tm0ZRZLezek8a1w08jZYxEa4bCwxrYdPhDN5ZvMtl6dx7dgfeWFgSr1j68Ai+WLmP5tERDGrfmJW7UunYrD4ncgpcvuRT8d/Nx1iz9wSPjOpcLt4AhqLu/sR8Jo3qzK2OwKmTD5fuZsrsLfx6z1CXC/XmofGlMgDd6RfXkJl3DCa3oJiZaw/w+E8lHVn7ntaQawa2JSI0hAu7t3DNX73nBD+uP0SP1tH8+/uNTBgSz53D27N4ewpje7XihblbeW/Jbt65pjf94xvRZ8qCUsf8/V/D2Hv8JAPaNS4V+8svKiY8NAS7XfHHgTR6t21Y7r+/lbizlKUcYhOK7YoGEaEu6/zGwXE8cUlXX061TxTbFYlbk0loHc3O5Gz6xDUsF8+rCKUUry3YQfdW0Qzu0Jh6dYz/PG/TUV6ev43tx7L56Ia+DD+jaamY06JtyWw8mME955xeaZkXbj1GboGdp37dVMpimnJpN64deFoFW5aQkVtIqE1YuTuVlKx8Lu3Viju/WEvS3jRm3DaQ6LphfLf2oMvaumNYeyZe2Mnr/o5m5NEkqg5Xf7DSo5upZXQE39w+iAZ1w9h0OINf/zxCs/oRhIUK1w48jfrhoV5jkCdOFlBkt5OdZ6RYD2jXmBMnC3jj9x1MX76X6LphrJ50zimvm92u6DJ5Lp2aN3B5BNx5akxXrh8UV2peTkER2XlFNG0QQVGxnQVbkhnWMZa6HmLEVaHL43PJKShm79TRPPvbFj5dvpetT19Q6lxMmJ7E0Yw8frvvzFPu77MVe7lhcPxapVTf6spWIy2ok/lFhNgV9eqEkplXxMvje3BZn9bcOaw9doXHIKb7g+kedGwZU5fOLRrw7uJdHmMudqUQKb19zzYx/LzhMI85LKFpbgrk5qHxHmV+8LyOrt9je7X2uM7ohBaMTmjB/hM5/OpwbaVkl85kaxlTl0dGdXZNd2rewOO+KuK8Ls04r4txDjw9kDbHPEX583E4PY96dULo6kg46NkmhraO4L+TqPBQYuqFcTAtl2aOt+q6dUJcLr9+cQ1J2ptGTkGxx3PRP74R/eMbUVhsJyO3kKv7t3W98YHhbv1qteHqaerYvzM+BUbGojMI746z8bDZhD6nNfJ4boafEetSUNF1w3j7mt5sPpzJ2N6tyM4rYsGWY4xOaOFx26oSYhPOdVwP5/+pDCLCA273l5ORXZszrGMs+UV217l3Z/gZTU9p5XrD+QwNPyOWrLwiLn5zGSlZ+ZzfpdkptizBKZO7hXV2p6YkbkspFT92cqpUcWeSQxNHQkmTqHCeHtOVnm1j2H4sm+4OixRgcPsm5Vz0FeHcrml9aOe4txpF1uHuER2oWyeEixJa+PRSYbMJHZpGeVROwzrG8o/+bcvNr1cn1PXSERpi8yk5pTIs+/fZrlTzpvXDyS+yk+nmogc4nJ5bYSawO9cPiuMGP8lWIxVUfpGdTo3qsfBfw9iZku1qpKvycDsRPMdclCppxJc8NIJCu73CjKDeboHLqvLsuO4kZ+azeu8JV5+mbq0akJlb5DHryt84FZSn83EkI5cW0RGICMsnnk2DumGs3mPE6VpER3BlvzaceXoTvlt7kK9XHyC2fkmq+ujuLTiSkcfV/dry7+//5I7h7SuUIyzExm1nlV8nNMTGfeeczpTZW1wZmQPbNXY99JWxPsrStWU0m54cyRsLd9AkMpwhHZowxOF+bBIVzt6po6u8bzOICAupMOusukSGhxIZHsrP/xzC5sOZ1XoGAbq1ii43r11sJLtTThIfG+lhi/I4FVSrmAiXZd4i2rfGtbLE1g/n3xd4t+o80fe0RqTnFDLzjkHUDQshI7eQNg3rVZisFUgaRdZxKWDn85qcmUdknRBO5hdzIC2HIxl59I2rfttWWWqkgsotLKZdbCShIbYqWRCeEJFyCQRgWFDO+6ZtY8NSqKhfRO/TYqotS4OIMJ6/PIERLy3iYFouIvD9nYOr1fBWBqdR5cmizMwrdLklW7r56MFoDO8/13iT33zY8M+792UKDbFxxzBD4TjjJ1VlVPcWTJm9hR2OxIiB7Rrx7uLynRSrQmR4KI9c2PnUK2pctIiu6xcl0LNNDK9c0YMOTaOoGxZCVEQoLaLrsmbvCfqc5lsD6VRQ7i9HVuLxi7rwyKhOrufZ3c1vNk3rGy8Y5726BJuUfkl1LgsmNVJBFRTZfTY3fcVm85wUoFSJReEkIiyEiRd24vSmUfy84TB1w0KYvfEIWXlFfntTcx7xYFoOTeuHB005QYmC8qiw7RBS5nx0aBrFRQktXMoHYGS35rwwbxvX+RiPqKqMh9JyCQ+10bNNTECOowkuIsK43uXdvn3jPLtkPdGkvtHgB/OZqQw2mxBus6ZszRqUKPURZzSl0K6oEyIs2JJMOx8tWH9SIxUUGJ0b/YkgFcSgypvezsbY6T9/8LyOfi0O61SKhcXKZakEC2eauSeFbVeqRHs6CAux8eY/epea17R+BBufGBkwGZ3nJyu/iPgmkZZ6C9WYS5ijf5G3zr8a77RuWI9zOzfl9mHtXX3JwOjg7Z7pGyxqpILq1LwBY3u18us+bYKHlADDxD1FcQHAiH9VLdzsGfdjeqroEEhsFVhQym25mbifnwYRxm389jW9yyVsaP5+NHS8rJjRoNZ06oTa+PCGfuXmd2haPukoGNRIBRUWIn5PFrCJeEmSUKY0yO4NsJQ1WQJMRUkSSilsNvPfTN3PidPCHdXdv9l1mprJuZ2b8vY1vSuVUaixJgFtaUQkV0QWOT43i0h7EVkrItkiMtRtvenu06YgnpMCPMWggoH7MYN9+IqSJHy1KAON+0uDFSw6jXUQEUZ1b1GulJCm5hFoC+qQUmq4c0JE6gHnAa8E+LiVxibiNeZihoKSUg1wcI/vtEg8uzzNOR9lcZfBCvJoNBr/E+hXjOYislhEZolInFIqRynlte69iLQQkfkiUi4HWURuE5E1IrImJSXF0+bVwuahTh14dnMFg9INcPCPb9Tt82xRnqridzAw08LUaDTBIdAKKk4pNQx4D/joFOt2Aj4H7lRKrS27UCn1vlKqr1Kqb2xsbPmtq4kRg/LUICvMCLmUikGZ5GL0ej6soBBMPj8ajSbwBLTpVUodd3zPA07VIWYy8KFSyj+9LauAx6QAzHEhuScBmKEQKrIoraAOdAxKo6n9BExBiUiUiIQ4ficAx0+xya3AjSJyfqBkqghbhZUkzLBgSn6bYSEY/cLKz1foGJRGowkOgUyS6AK8JyJZGIbI7SLSAJjlWNZVRH5TSk12rJ8NjANmikiYUmp2AGUrh7dKEmZZDJaIQXlIk7DbreFS0wpKo6n9BExBKaVWA708LDrXw7o3uk2aUo2z4koSJshjYj8oqNiitII+KB2jM08OjUYTOHRHAQfeKklgUj8odyvFrCQNu5cURivEfMxOItFoNIHnlBaUiDQFhgAtgVzgL2CNUqriwVlqGOKlkoQlLCiTsvhqTj8oEwXRaDQBw6uCEpERwESgEfAHkAxEAJcC7UXkO+BlpVRmEOQMON76/ZiXJGFujMUYH8u6lSTcRbCCwtRoNP6nIgtqFHCrUmp/2QUiEgpchFEV4vsAyRZUvMdczLJgSn6b0fyKlzRzT0PEm4G2oDSa2o9XBaWUeqiCZUXAj4EQyCxsFdbiC748pveDsnku/WRWbcKylBbBfHk0Go3/OWX4XUTuE5EGYvCRiKwzq69SIJEKKieYHYMyz8VXfr5dKUuoAxFxnSNtQWk0tRNf8sMmOOJM5wMNgeuAqQGVygQqapDNjkGZlyThOQZlFYXgFMMKFp1Go/E/vigo59M/CvhcKbWJWuhTsYnnPHOFSZUcTO7nI+Kt9JM1svigRDFZYHgqjUYTAHx5tNeKyHwMBTVPROoDtSrFHIxGzlvWmjm18MyuJOElacQilSSg5BxZRR6NRuNffKkkcTPQE9itlMoRkcbATQGVygS8VZJQJsVcbCbHoGxeh9uwRiUJKLEsLSKORqPxM75YUAqjdt69julIjP5QtQovHj4TByw0d7wjrwobC8WgXEkSFhFIo9H4FV8U1NvAIOBqx3QW8FbAJDIJm5dKEmamVbssBNMsqPLzrVJJAtxiUNYQR6PR+BlfXHwDlFK9ReQPAKVUmojUCbBcQaeiShJm+ZAE8ywW76WfrFFJAtwVlEUE0mg0fsUXC6rQMa6TAhCRWGpjkkQFlSTMekM3swG2+pDv4PbeYA1xNBqNn/FFQb0B/AA0FZFngGXAswGVygS8V5Iwz6XlylIz6dieYnKWGfIdHYPSaGo7p3TxKaW+FJG1wDkYbeWlSqktAZcs6FgvBoWJMSjxorCNShLWUAg2m45BaTS1mYqqmTdym0wGvnZfppQ6EUjBgo23tGozB+izmWgheHN5WimLT8egNJraTUUW1FochRQc087myhm7bxdAuYKO1aqZg7lZal4tKLs1qplDyY1pFXk0Go1/qaiaeXwwBTEbb5UkzIy5lDTA5hzb83Ab1snicyomq8ij0Wj8iy/VzMeKSLTbdIyIXOrLzkUkV0QWOT43OyqiTxORpSLyq9ONKCLTRWRolf+FH6i4Y6rZFpSVisVaqR9U6W+NRlO78CWLb7JSKsM5oZRKByb7uP9DSqnhjs9HwEignlLqTOBb4OHKChwoKqokYVb7Z2ZHXRGj7l5ZdAxKo9EEC18UlKd1fOngC9BcRBaLyCwRiQOGAb86lv3imHYhIi1EZL6I9PFx/37DawzKxOKoYmIMqiZYUDrNXKOp3fiioNaIyCsi0t7xeQUjgcIX4pRSw4D3gI+AxkCaY1k6xvhSTjoBnwN3KqXK7V9EbhORNSKyJiUlxcfD+05FadXmddQ1vs0ZbsN7JQmLZJm7VTM3WRCNRhMQfFFQ9wAFwDfADCAPuNuXnSuljju+5wGnASeAGMfiaEqUFRhuww+VUru87Ot9pVRfpVTf2NhYXw5fKbxZUM5lZiAmurCMJAnPeeZWsVhKqplbQx6NRuNffHHVtVNKTazsjkUkCshVShWLSAJwHFgMjAV+xBhfarHbJrcC94vICaXU/Moer7pU2DHVdAvKhCQJW0XFYoMujkf0kO8aTe3GFwX1toiEA58AX7knTJyCLsB7IpKFEVu/HdgIXCQiS4FM4Hq39bOBccBMEQlTSs329U/4A6GiWnympUkAJvWD8pLVaKlKEq4Rda0hj0aj8S++lDo6U0Q6YgxSuFZEVgOfKKX+e4rtVgO9PCwq5x5USt3oNjn6VDIFAm+1+My0oJyYoRBsXrIarZjFZ/b10Wg0gcGXGBRKqe3Ao8C/MTLv3hCRrSIyLpDCBROvMSgLVO+2ynAbSilrVTPXWXwaTa3Gl466CSLyKrAFOBu4WCnV2fH71QDLFzS8VZKwQszFDBeWp+E2nJNW0QdS5luj0dQufIlBTQM+BP6jlMp1zlRKHRaRRwMmWdDxnlZt3hu6IZAZh/dkUSq3ZVZAd9TVaGo3viio0Tiy8QBExAZEKKVylFKfB1S6IGIYKToG5cRTTM45bbZF6UQP+a7R1G58iUEtAOq6TddzzKtV2Lx0TDVGfNdZfFCioKwWg7KKPBqNxr/4oqAilFLZzgnH73qBE8kcvPWDMncEWafFYlYMqow0FotBOdEuPo2mduKLgjopIr2dE446ebkVrF8jqWg8KLMbQHNKHXlXUGafj7JYTByNRuMnfIlB3Y/RefYwhs+pOXBlIIUyA68WFAqbT8n4gcOUShIiFFO6nLnVYlBOrCaPRqPxD7501E0SkU7AGY5Z25RShYEVK/hUVEnC7ERms6qZl43JuWJQFkvs1jEojaZ24tU2cB9AUClVqJT6y/EpdCxvICLdgiFkMPBWScLcGJSBWTGosudDuS2zElZzOWo0Gv9QkQV1mYi8AMzFGF4jBYgAOgAjMKqT/yvgEgYJm816MSgzkxLEUz8oh8fPagrBYuJoNBo/4VVBKaUecAzJfhkwHmiBkRyxBXhPKbUsOCIGB8G6FpQpI+pSvpJESZp50MWpELOvj0ajCQwVxqCUUieADxyfWo0niwEMC8q8EXWNb3NiUOW7LVutkoQTq8mj0Wj8g8n5adbBaJCtVUnCzLRuI0nC2pUknOgkCY2mdqIVlIOKKkmY/YZuxtFFwF46y7xEYVlMIVhNYWo0Gv+gFZSDiipJmN3+mZPFJ+VdfC6LLujiVIjFxNFoNH7Cl+E21orI3SLSMBgCmUVFMSizR2w1JYsP78NtmG1RlsXs66PRaAKDLxbUlUBLIElEZojISKmFTn9nG+cpc83sf2tWDKqswtYxKI1GE0xOqaCUUjuVUpOAjsBXwMfAPhF50pGGXitwVkcoP4qs+RaDKeNBeRjA0aqVJKymMDUajX/wKQYlIgnAy8CLwPcY/aIygYWBEy24eLOgFH/TGJSH4TasliNhVZejRqPxD6esxScia4F04CNgolIq37FolYgM8WH7jsAmjOoTO4BPgXBgP3CbUipfRBYB1yqlDlblT/gDZxyjfP058xtA06qZl5lnVYVgLWk0Go2/8MWCGq+UOkcp9ZWbcgJAKTXOh+0fAxY7fj8CTFdKjQA2A9dXStog4MmtZZYLycyOsRXFoKyin0o6MltEII1G41d8UVC3iEiMc0JEGorIFF92LiIDgKOA0zLqCKxx/F6NYVW5r99ZRBaISDtf9u9PnI2cpzGQzA7Cm2VBeSsWazWFYDFxNBqNn/BFQV2olEp3Tiil0oBRPu5/EjDVbXojcIHj9yjAPcliMPAqcLVSanfZHYnIbSKyRkTWpKSk+Hh433HFoNwcW8pki8F5WG1BecaqLkeNRuMffFFQISIS7pwQkboYMaQKEZHRwBqlVKrb7GeBASKyECP+ddht2UvAk0opj9pHKfW+UqqvUqpvbGysD2JXDmcj5x6DspvcAJZYLME/tqfiuSUK21oKwewBJTUaTWDw5dH+EvhdRG4WkZuB/2IkOpyKnsBwEZkLnIehgGKUUtcppc7GqIz+ndv644DnRaRXZf6Av3C2ue6NslX6/ZhSzdzTcBuWrSRhMYE0Go1f8GVE3edF5E/gHMesp5VS83zY7hngGQARmQ58CLR3/LYDvyulfnPb5CjG0B4zReQhpVRSZf5IdREPMSi7RSwGM45uE0+dlp3LrKUQLCaORqPxE6dUUABKqTnAnKoeRCl1o9tkub5TSqnhbpPDyy4PBp76QVml3495I+qWnlfSUddaWE1hajQa/+BLLb5xIrJDRDJEJFNEskQkMxjCBRNnE+feKFslCG9GjMUmUm74EatYlGUx+/poNJrA4IsF9QJwsVJqS6CFMRNnR11loRiUmUkJniwoy8agLCaPRqPxD768mx+r7coJSpSA3VMMymSnljnjQVWUJGEtjWA1hanRaPyDLxbUGhH5BvgRcFWSUErNCpRQZuBs40rFoJzLzOoH5TiwOf2gPFd2N+QKujgVYjWXo0aj8Q++KKgGQA5wvts8BdQqBeWpH5Syl14WbJTLxWiRYrGOb+tZUNaSR6PR+Adf0sxvCoYgZuOpkoTZMSgnZhzf5qFYrFUtKLOvj0ajCQy+ZPF1FJHfReQvx3SCiDwaeNGCS0lH3ZJ5JS4+s3vqmnBIEexlsiSsWknCYuJoNBo/4UuSxAcYVcgLAZRSfwJXBVIoM3AlSditaEGZk8XnfbiNoItTIVZTmBqNxj/4oqDqKaVWl5lXFAhhzMSTErBKvx/rFIs1T56KsJo8Go3GP/iioI6LSHscL9QicjlwJKBSmYDN5eIrX0nC7AbQKsVirVZJwhkvtJpFp9Fo/IMvWXx3A+8DnUTkELAHuCagUpmAxxiURUodmXF8m817PyizLcqymP0CodFoAoMvCkoppc4VkUjAppTKEpH4QAsWbEoGLLReDMq8ShKekyTMPh9lsZg4Go3GT/ji4vseQCl1UimV5Zj3XQXr10gqrCRh+nhQ5vSD8haDsooF5azwYRV5NBqNf/FqQYlIJ6ArEC0i49wWNQAiAi1YsPFYScIiMSjThtvwUizWKhaUjkFpNLWbilx8ZwAXATHAxW7zs4BbAyiTKXisJOG0GEyQxx2rDLdhmX5hZbBpDaXR1Eq8Kiil1E/ATyIySCm1IogymUKFlSRMHlLclCQJEa+1+KymD6wmj0aj8Q++JEn8ISJ3Y7j7XK49pdSEgEllAq4sPnvJPLuJtfDcMceCEg/DbVijX1h5rCaPRqPxB77YBp8DzYGRwGKgNYabr1ZRkiThbkGZJU1pzNAHFcfkgi9PRVhNHo1G4x98UVAdlFKPASeVUp8Co4EBgRUr+Hi2Uv6+FlRJ2n3JPF1JQqPRBBNfFFSh4ztdRLoB0UDTwIlkDp4qSVilQTalkoTH82ERk7IMZl8fjUYTGHxRUO+LSEPgUeBnYDPwvK8HcFRDLxSRoSLSTkSWiMgiEUkUkdaOdRY5f5uFp0oSVkkKMCPmU5I0UoJV0u7LYjFxNBqNnzilglJKfaiUSlNKLVFKtVNKNQWOV+IYj2HErgDuAj5SSg0HPgXuqazAgUJcLi03i8HuXGaGRCWYEoPyEJNTFslqLIvZ10ej0QSGqjY1r/qykogMAI4CBx2zNmH0qwJoCCSXWb+ziCwQkXZVlKvKeOwHhTWy1szqBwWeY1Bisaw5q1l0Go3GP/iSZu4JX1uEScBNwMuO6QXAPBG5GQgH+rutOxiYAFytlEopd0CR24DbANq2bVtFsb1jxUoSZmbNeUqSsGrlBq2fNJraSVUtqFNGy0VkNLBGKZXqNvt54FGlVALwBPCs27KXgCc9KScApdT7Sqm+Sqm+sbGxVRTbO54sKKvEoMypxWfgKWnEbIvSibKoRafRaPxDRbX4NuJZEQnQzId99wSGi8hgoDvQCcilJH6VDDRyW38c8IqI3KeU+sOH/fsVV1KAxwY52NKYj8uCcptn1WrmGo2mdlKRi++i6uxYKfUM8AyAiEwHPgTSgPdEpAgIA2532+QocBkwU0QeUkolVef4lcbjeFAWiUGZoBEqSjM3+3w4sYgYGo0mQFRUi2+fvw6ilLrRbXKoh+XD3SaHl10eDDyPB1V6mVmY0w/KcT7cSj9ZtZKERqOpnVgsYdg8rOzSMqeShPFduniuefJ4wqL9hjUajZ/QCsqBZ5eWY5nJQXhzxoPynjRiNSyiLzUajZ/RCsqBrUwMKiOnkI2HMkotMwuzhnyHMkrJaUGZfULKYFG9qdFoqkmVFJSIPOFnOUynbCWJh77bwNO/bi61zCxMjUFZMO1eo9H8PahqR921fpXCAjhdWuk5hRzLzGPJjhRaRkcwtncrerWNMUWmkhiYef2gdhzLItQmNIysYxmXZ1m0i0+jqZ1USUEppX7xtyBm42zj7v9mvWveM2O7M6KT+YXbzRpRF+AfH65CBF67siffJO13LAu+PKV44QXo149SDoDEREhKgocfNk0sjUbjX06poETkDQ+zMzCqRPzkf5FM4IUXaBDXGfcG7z91j3Dmjx/DxInmyWUi7tl7SsF9M9a7ps12edKvH1xxBT3GT2JHg9Opu2wJ3HEjfPutuXJpNBq/4ksMKgKjKsQOxycBY1Tdm0XktYBJFkz69SPu7gkM2vcnALM65XHbm48QOsAa4zKa4VKLrGO8u9wyNJ5HR3ema8sGJfKYbUGNGAHffsujnz3BA0u/oMVtNxjKacQIkwXTaDT+xBcXXwIwRClVDCAi7wBLMTrcbgygbMFjxAjk22955+KxfNrjQnp+uABmmtjguVxYbgTZhTWqewvaxUaS0DoGXniBW/r1I+6wscwmYr5LbcQITk64lfumvUTRpElaOWk0tRBfLKiGQJTbdCTQyKGw8gMilRmMGEHY3Xdx3/IZ2O6609wGz+HC6rdnAwAhixfBFVeUV1oBpE6ozVBObvI4Lcw6S4IvTzkSE2n19XR47DFC33vPUJgajaZ2oZSq8APcDOwBPgGmA7uBWzAU1Yun2j4Qnz59+ii/s3ChUk2aKPXYY8b3woX+P0Yl5UmPilGvDb5K2S0iT2q9aPXa4KtUcWOT5XFeK6cMZac1Go2pYOQoVLut920laAGMcXxa+uPA1fn4XUFZtMHLnfgf4xI99pipcjhJffBhpUDZH33UXEGef778tVm40Jiv0WhMx18KStQpuuGLyC/AV8DPSqmTgbDiKkvfvn3VmjVr/LdDZ8zH3a1ndowlMdFwo915J7zzjvlJAFaTR6PRWBYRWauU6lvt/figoIYBVwKjgSRgBvCrUiqvugevKn5XUFbDqQycSqDs9N9dHk2tobCwkIMHD5KXZ1pzoqkGERERtG7dmrCwsFLz/aWgTpnFp5RaDCwWkRDgbOBW4GOgQYUbaqpOUlLpxt+RVk1SkjkKwWryaGoNBw8epH79+sTFxZnfv05TKZRSpKamcvDgQeLj4wNyjFNaUAAiUhe4GMOS6o1hQd0TEIl8oNZbUBrN34QtW7bQqVMnrZxqKEoptm7dSufOnUvN95cFdco0cxH5FtiCYT29CbQ3UzlVlunTpzN48GCGDBnCunXrvK43d+5cBg0axKBBg5g3bx4A8+bNY+DAgQwbNoxRo0aRmpoKwA8//EDnzp2JiIgIyn/4O1Gd67Vo0SJuueWWYImq8RNaOdVcAn7tTpVFAYwEQtymhwJv+SNDo6ofX7P4Tpw4oXr16qXy8/PV7t271ZAhQzyuV1RUpLp3767S0tJUWlqaSkhIUEVFRWrfvn0qLy9PKaXUW2+9pR51ZK8dP35c5ebmqvbt2/skh8Y3qnu9EhMT1c033xxkqTXVYfPmzWaLoKkmnq4hfsriO6UFpZSaBySIyAsishd4GtgaMI3pR1avXs2ZZ55JnTp1iI+PJysri+eff56nnnoKgBtuuIFZs2axc+dO4uPjiYmJISYmhri4OHbu3Enbtm0JDw8HIDw8nNBQI2TXuHHjKltP1bEQ9u7dS8OGDRk+fDjDhw9n9uzZpbaZPHkyHTp0qJJcVqC61wtg165djB07lp49ezJz5kwAvvrqK0aMGMGgQYO45ZZbnC9aGg0AUVFRp17JwaJFi1i+fHkApdG441VBiUhHEZksIluBacABjJjVCKXUtKBJWA1SU1Np2LChazomJobrr7+elStXcv/99xMZGcm4ceM8rnfixAnX9LFjx3jzzTe58847qyVPWloab7zxBosWLeKLL77g3nvv9bhecXExDz/8MHPmzGHOnDk8/PDDFBcXA9CnTx8WLVrEokWLGD16dCkZt2/fXmmZqqMwCwoKuOKKKzjzzDMZMGAACxcuBOCVV15xKdH4+Hj+9a9/+SSLP65XSkoKM2fOZMmSJUyaNAm73c6YMWNITExkxYoVZGVlsXTp0kqfJ40GtIIKNhVl8W3FqLl3kVJqJ4CIPFDZA4hIR2ATMALoD1ziWHQaMEsp9S8RWQRcq5Q6WNn9V0SjRo1IT093TWdkZNCoUSMeeOABLrzwQvbv31/hegCZmZlcfvnlvPvuuzRtWr2hN7xZCPn5+Tz++OPccMMNjBkzhq5du7osBMBlIYSHh7NhwwbOPPNM4uPjefXVV2ncuDEATz/9NI888gjjxo3zWR6nwly5ciWHDh3iuuuuY9myZeXWcyrMJUuWADBs2DDOPfdc5s+fT2RkJEuXLmXv3r1ceeWVrFq1igcffJAHH3wQgFGjRjF+/Hif5Knu9Tpy5Ai9evUiNDSUBg0a0LRpU1JSUli3bh0vvvgixcXF7Nu3j0suuQSN9Xjyl01sPpzp1312admAyRd3rfR2v/zyC1OmTKGgoIDGjRvz5Zdfkpuby7vvvktISAhffPEF06ZNo1OnTtxxxx2ue/O1115jyJAhPPHEE+zfv5/du3ezf/9+7r//ftcL6WeffcZLL72EiJCQkMDbb79NQkIC27dvJywsjMzMTHr06OGa/jtTkYtvHHAESBSRD0TkHKhSWe3HgMUASqlXlFLDlVLDMRIvZlZhfz4zYMAAli1bRmFhIfv37ycqKoqioiImT57Mu+++67phTj/9dPbs2UNmZiaZmZns2bOHDh06kJuby9ixY5k0aRID/FDZvLoWQosWLdi9ezdLly5l6NChPOzoRLxjxw6ys7NJSEiolDzVdam1b9+e/Px8lFKkpaWVU+DJycns2bOHgQMH+iRPda8XwPr16ykqKiIrK4tjx44RGxvLxIkT+fLLL1m8eDEDBgzQLj7NKRk6dCgrV67kjz/+4KqrruKFF14gLi6OO+64gwceeID169dz5plnct999/HAAw+QlJTE999/XypJZ+vWrcybN4/Vq1fz5JNPUlhYyKZNm5gyZQoLFy5kw4YNvP7669SvX7+Uy37GjBmMGzfub6+coAILSin1I/CjiERilDi6H2jqqGb+g1Jq/ql2LiIDgKNAcZn5TYF4pdTKMvM7Y7gTb1NK7a7cXylPw4YNueuuuxg2bBgiwuuvv84999zDgw8+yOWXX86OHTt4++23ueuuu3juuecYOXIkAM899xwhISG89dZbbNiwgalTpzJ16lTOO+88Jk2axNKlS3nyySc5fPgw5557LnfddZdPlkt1LYTw8HBXTOzaa6/lrbfeAuCJJ55wKZXK4E1h3nzzzaUU5vLlyz0qzN69e5Obm0unTp1IT0/nl19Kj2M5Y8YMrrjiCp/lqe71AmjZsiXjx49nz549TJkyBZvNxvXXX895551Hp06dKn2ONMGjKpZOoDh48CBXXnklR44coaCgwGs/nwULFrB582bXdGZmJtnZ2QCMHj3a9cw2bdqUY8eOsXDhQsaPH0+TJk0AXJ6aW265hRdeeIFLL72UTz75hA8++CDA/7CGUJmMCozK5rcBv/u4/s9AY4wis0Pd5t8LPOk2vQi4ApgLxHrZ123AGmBN27Ztq5JsYjonTpxQffr0UQUFBWrfvn1qyJAhKjs7Ww0aNEh98MEH6rLLLlNKGVlqCQkJKiMjQ2VkZLiy1NLT0137+uWXX9T48eOVUkoNHDhQjRw5Uo0cOVLVq1dP3XPPPT7JM2fOHHXfffe5pnv06KHy8vLU/PnzVUhIiDp06JBSSqktW7aoMWPGuNYbM2aM2rp1q3rvvfdcx9qzZ4/q1atXqf33799fbd++vdLnSfP3wQpZfJGRkeXmDRs2TP30009KKaUSExPVsGHDlFJKTZ48Wb344ouu9Ro3bqxyc3PLbV92va5du6o9e/aoN954Q/3nP//xKEdCQoJKTExU/fr1q87fCTqmZvGVUWZpSqn3lVLnnGpdERntEDLVw+JrgC/KzHvJobRSvBz7faVUX6VU39jY2MqIbRncLYSrr76a1157zWUh3HLLLbRv3563336bkJAQl4UwcuRIl4WQmJhI7969GTZsGNOmTeOll14CYMWKFcydO5e5c+fSokUL3njD0yDI5amuS00p5XoTbNiwIVlZWa59b9++HRHh9NNP9/NZ1GgCT0ZGBq1atQLg008/dc2vX79+qfv8/PPPZ9q0kpyx9evXV7jfs88+m5kzZ7r6VLonY11//fX84x//4KabbvLHX6gd+EPLefoAk4CFGFbRIWAlRmJER2BlmXUXAX2BJUCvU+07IMNt/E356KOP1KBBg9TgwYNVUlKSuummm9TMmTOVUko9/PDD6q233lJKKTV79mw1cOBANXDgQDV79myllFLZ2dnq4osvVmeddZbq27ev+uabb1z7feyxx9Qbb7wR/D+kqVFYwYISEdWqVSvX5+WXX1Y//vijio+PV71791b/93//57Kgtm3bprp376569OihlixZolJSUtQVV1yhunfvrjp37qxuv/12pZR3C0oppaZPn666du2qEhIS1A033OBa58iRIyoiIkKlpaUF6Z/7h0BaUD6VOqouIjId+FAptUxEngJSlFuqujOLD2MAxJnAQ0qpJG/706WONJrawZYtW8qVyfm78t133/HTTz/x+eefmy1KpfB0DYNWLNYfKKVudPv9uIflw90mh5ddrtFoNLWZe+65hzlz5vDbb7+ZLYqlCIqC0mg0Go133ONYmhIqlSSh0Wg0Gk2w0ApKo9FoNJZEKyiNRqPRWBKtoDQajUZjSbSC0mg0NYMXXoDExNLzEhON+VVkxIgRrur8Tl577TXuvPNOfv75Z6ZOnep12/T0dN5++23X9OHDh7n88surLMsTTzxBq1at6NmzJ926dePnn392zXd2yvdGXFwcx48f9/lYe/fupVu3blWWNVhoBaXRaGoG/frBFVeUKKnERGO6X78q7/Lqq69mxowZpebNmDGDq6++mksuuYSJEyd63basgmrZsiXfffddlWUBXIVoZ86cyYQJE7Db7dXaX01HKyiNRlMzGDECvv3WUEqPP258f/utMb+KXH755cyePZuCggLAsCwOHz7MmWeeyfTp0/nnP/8JGOOtjR07lh49etCjRw+WL1/OxIkT2bVrFz179uShhx4qZZVMnz6dSy+9lPPOO4+4uDjefPNNXnnlFXr16sXAgQNLlTjyROfOnQkNDa2UVeSUv3Pnztx666107dqV888/n9zcXADWrl3rkt9ZaBqM4XQeeugh+vXrR0JCAu+99x4Ar776KhMmTABg48aNdOvWjZycnErJU120gtJoNDWHESPgzjvh6aeN72ooJzCqiffv3585c+YAJRX4RUqPLHTvvfcybNgwNmzYwLp16+jatStTp06lffv2rF+/nhdffLHcvv/66y9mzZpFUlISkyZNol69evzxxx8MGjSIzz77rEK5Vq1ahc1moyp1R3fs2MHdd9/Npk2biImJ4fvvvwfgpptuYtq0aWzYsKHU+h999BHR0dEkJSWRlJTEBx98wJ49e7jvvvvYuXMnP/zwAzfddBPvvfce9erVq7Q81UErKI1GU3NITIR33oHHHjO+y8akqoC7m8/p3ivLwoULXSNqh4SEEB0dfcr9jhgxgvr16xMbG0t0dDQXX3wxAN27d2fv3r0et3n11Vfp2bMn//d//8c333xTTlH6Qnx8PD179gSMEbj37t1Leno66enpnHXWWQBcd911rvXnz5/PZ599Rs+ePRkwYACpqans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",
      "text/plain": [
       "<Figure size 432x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Demonstrate the load->store channel with port contention\n",
    "# Correspond to Figure 8\n",
    "\n",
    "def plot_vpn_contention(step=2000, **kwargs):\n",
    "    name = 'vpn_contention'\n",
    "    lats = run_bino(CORES, name, **kwargs)\n",
    "    offsets = np.arange(0, 0x200)\n",
    "    peaks = peak_seeking_std(lats, 4, reverse=True)\n",
    "    fig, ax = plt.subplots(figsize=(6, 3))\n",
    "\n",
    "    ax.plot(offsets, lats, label='Latency')\n",
    "    ax.plot(offsets[peaks], lats[peaks], 'rx', label='Victim PL Index')\n",
    "    for i, peak in enumerate(peaks):\n",
    "        ax.text(offsets[peak], lats[peak] - step // 2,\n",
    "                f'{offsets[peak]:#05x}', ha='center', fontsize=9)\n",
    "\n",
    "    ax.set_xlim(offsets[0], offsets[-1])\n",
    "\n",
    "    max_y = ax.get_ylim()[1]\n",
    "    min_y = np.floor(ax.get_ylim()[0] / step - 1) * step\n",
    "    ax.set_ylim(min_y, max_y)\n",
    "\n",
    "    ax.set_xticks(list(np.arange(0, 0x200, 0x40)) + [0x1ff])\n",
    "    ax.set_xticklabels([f'{t:#x}' for t in ax.get_xticks()], fontsize=9)\n",
    "\n",
    "    ax.set_yticks(np.arange(*ax.get_ylim(), step))\n",
    "    ax.set_yticklabels([f'{t / 1000:.0f}k' for t in ax.get_yticks()], fontsize=9)\n",
    "\n",
    "    ax.set_xlabel('PL Index', fontsize=10)\n",
    "    ax.set_ylabel('Avg. Latency (cycles)', fontsize=10)\n",
    "    ax.legend(loc='lower right', fontsize=10)\n",
    "\n",
    "    fig.tight_layout()\n",
    "    fig.savefig(RES_DIR / f'prim_{name}_{platform}.pdf', bbox_inches='tight')\n",
    "\n",
    "plt.close('all')\n",
    "rebuild()\n",
    "fig = plot_vpn_contention(step=1000, iters=5)\n",
    "plt.show(fig)"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
  },
  "kernelspec": {
   "display_name": "Python 3.8.10 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
